package cn.kai.ymcc.service.impl;

import cn.kai.ymcc.constants.RedisConstant;
import cn.kai.ymcc.domain.CourseType;
import cn.kai.ymcc.dto.CourseCrumbsDto;
import cn.kai.ymcc.mapper.CourseTypeMapper;
import cn.kai.ymcc.result.JSONResult;
import cn.kai.ymcc.service.ICourseTypeService;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author kai.tang
 * @since 2022-07-20
 */
@Service
@Slf4j
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    /**
     * 获取课程面包屑
     * @param courseTypeId
     * @return
     */
    @Override
    public JSONResult getCrumbs(Long courseTypeId) {
        //获取coursetype
        CourseType courseType = selectById(courseTypeId);
        String courseTypePath = courseType.getPath();
        //获取path并转成list
        String[] paths = courseTypePath.split("\\.");
        List<Long> pathsList = Arrays.asList(paths).stream().map(Long::valueOf).collect(Collectors.toList());

        List<CourseCrumbsDto> courseCrumbsDtoList = new ArrayList<>();

        for (Long typeId : pathsList){
            //获取当前courseType
            CourseType courseTypeTemp = selectById(typeId);
            //获取当前courseType的同类
            Wrapper<CourseType> tWrapper = new EntityWrapper<>();
            tWrapper.eq("pid",courseTypeTemp.getPid());
            List<CourseType> courseTypesTemp = selectList(tWrapper).stream().filter(t -> t.getId() != courseTypeTemp.getId()).collect(Collectors.toList());
            //生成courseCrumbsDto
            CourseCrumbsDto courseCrumbsDto = new CourseCrumbsDto(courseTypeTemp,courseTypesTemp);
            //将生成的courseCrumbsDto放入最终结果集
            courseCrumbsDtoList.add(courseCrumbsDto);
        }

        return JSONResult.success(courseCrumbsDtoList);
    }

    /**
     * 查课程分类树
     * @return
     */
    @Override
    @Cacheable(cacheNames = RedisConstant.COURSETYPE_TREE_REDIS_KEY,key = "'key1'")
    public List<CourseType> treeData() {
        log.info("走的MySQL");
        return tree();
    }

    public List<CourseType> treeData2() {
        //1.从缓存读数据
        Object obj = redisTemplate.opsForValue().get(RedisConstant.COURSETYPE_TREE_REDIS_KEY);
        if (obj!=null){
            //2.有直接返回
            log.info("走的redis");
            return (List<CourseType>)obj;
        }
        //3.没有查数据库将数据放入缓存
        List<CourseType> types = tree();
        log.info("走的MySQL");
        redisTemplate.opsForValue().set(RedisConstant.COURSETYPE_TREE_REDIS_KEY,types);
        return types;
    }

    public List<CourseType> tree() {
        List<CourseType> courseTypes = selectList(null);
        //为了后面找自己的父亲，我们这里可以把整体的部门数据，转换一份成Map<id,courseType>
        //Map<Long, CourseType> allCourseTypes = courseTypes.stream().collect(Collectors.toMap(CourseType::getId, dept -> dept));
        Map<Long, CourseType> allCourseTypes = new HashMap<>();
        for (CourseType courseType : courseTypes) {
            allCourseTypes.put(courseType.getId(),courseType);
        }
        //新建一个集合用来存放顶级部门
        List<CourseType> firstCourseTypes = new ArrayList<>();

        for (CourseType temp : courseTypes) {
            //如果父级id为null，则为顶级部门
            if (temp.getPid()==null || temp.getPid()==0){
                firstCourseTypes.add(temp);
            }else {
                //以父类id为key值查出父类元素，因为map中赋值为引用类型CourseType元素的地址值。所以修改共享有效
                CourseType parent = allCourseTypes.get(temp.getPid());
                if (parent != null){
                    parent.getChildren().add(temp);
                }
            }
        }
        return firstCourseTypes;
    }

    @Override
    @CacheEvict(cacheNames = RedisConstant.COURSETYPE_TREE_REDIS_KEY,key = "'key1'")
    public boolean updateById(CourseType entity) {
        return super.updateById(entity);
    }

    @Override
    @CacheEvict(cacheNames = RedisConstant.COURSETYPE_TREE_REDIS_KEY,key = "'key1'")
    public boolean insert(CourseType entity) {
        return super.insert(entity);
    }

    /**
     * 延迟双删
     * @param id
     * @return
     */
    @Override
    public boolean deleteById(Serializable id) {
        redisTemplate.delete(RedisConstant.COURSETYPE_TREE_REDIS_KEY+"::key1");
        boolean delete = super.deleteById(id);
        redisTemplate.delete(RedisConstant.COURSETYPE_TREE_REDIS_KEY+"::key1");
        return delete;
    }
}
